home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-09-02 | 18.4 KB | 521 lines | [TEXT/CCL2] |
- ;;; number-line-view.lisp
- ;;;
- ;;; Paul McCartney, Spring 1992
- ;;;
- ;;; Copyright © 1992 Paul McCartney. All Rights Reserved.
- ;;;
- ;;; Washington University Medical Informatics Training Program
- ;;;
- ;;; DESCRIPTION:
- ;;;
- ;;; This file provides a new type of dialog item. The item is a
- ;;; number line that can be dragged or rescaled by the user in real time.
- ;;;
- ;;; USE:
- ;;;
- ;;; number-line-vertical-view - dialog item class for vertical scales
- ;;; number-line-horizontal-view - dialog item class for horizontal scales
- ;;; :title - title of the number line
- ;;; :scroll-p - allow scrolling?
- ;;; :rescale-p - allow rescaling?
- ;;; :dialog-item-action - fn called after scroll or rescale by the user,
- ;;; takes the dialog item as an argument
- ;;; :start - initial start value of the number line
- ;;; :end - initial end value of the number line
- ;;; :min-value - minimum start value
- ;;; :max-value - maximum end value
- ;;; :rescale-cursor - cursor to use during rescale
- ;;; :scroll-cursor - cursor to use during scroll
- ;;; :tick-mark-inc-fn - fn to determine the increment for tick marks.
- ;;; takes the drawing scale as an arg
- ;;; :string-trans-fn - fn to transform a number line value (number)
- ;;; into a string (any string...)
- ;;; :title-font-spec - font of the title
- ;;; :mark-font-spec - font of the tick marks on the number line
- ;;; :number-line-width - width of the number line
- ;;;
- ;;; set-number-line-range - set start and end of the number line
- ;;; number-line-start - access start
- ;;; number-line-end - access end
- ;;;
- ;;;
- ;;; HISTORY:
- ;;;
- ;;; 7/20/92 Removed remaining QD dependencies. - PM
- ;;; 7/13/92 Fixed rescale cursor bug. - PM
- ;;; 6/29/92 Added GWorld offscreen graphics smoothing. - PM
- ;;; 4/10/92 Created. - PM
- ;;;
-
- (in-package :ccl)
-
- (eval-when (:compile-toplevel :load-toplevel :execute)
- (export '(number-line-horizontal-view number-line-vertical-view
- set-number-line-range number-line-start number-line-end)
- :ccl))
-
- (require :GWorld-view-extensions)
- (require :graphics-tools)
-
-
- (defclass number-line-view (dialog-item)
- ((title :accessor title :initarg :title)
-
- (scroll-p :accessor scroll-p :initarg :scroll-p)
- (rescale-p :accessor rescale-p :initarg :rescale-p)
-
- (scale :accessor number-line-scale)
-
- (number-line-rect :accessor number-line-rect)
-
- (start-value :initarg :start :accessor start-value)
- (end-value :initarg :end :accessor end-value)
- (min-value :initarg :min-value :accessor min-value)
- (max-value :initarg :max-value :accessor max-value)
-
- (number-line-width :initarg :number-line-width :accessor number-line-width)
-
- (tick-mark-inc-fn :initarg :tick-mark-inc-fn :accessor tick-mark-inc-fn)
- (string-trans-fn :initarg :string-trans-fn :accessor string-trans-fn)
-
- (rescale-cursor :initarg :rescale-cursor :accessor rescale-cursor)
- (scroll-cursor :initarg :scroll-cursor :accessor scroll-cursor)
-
- (mark-font :initarg :mark-font-spec :accessor mark-font)
- (mark-ff :initarg :mark-ff :accessor mark-ff)
- (mark-ms :initarg :mark-ms :accessor mark-ms)
-
- (title-font :initarg :title-font-spec :accessor title-font)
- (title-ff :initarg :title-ff :accessor title-ff)
- (title-ms :initarg :title-ms :accessor title-ms)
-
- (color-list :initarg :color-list :accessor color-list))
- (:default-initargs
- :title '("Untitled")
- :view-position #@(0 0)
- :scroll-p t
- :rescale-p t
- :start 0
- :end 10
- :min-value 0
- :max-value 10
- :rescale-cursor *arrow-cursor*
- :scroll-cursor *arrow-cursor*
- :string-trans-fn #'princ-to-string
- :title-font-spec '("times" 14)
- :mark-font-spec '("times" 10)
- :color-list ()
- :number-line-width 15))
-
-
- (defclass number-line-vertical-view (number-line-view)
- ()
- (:default-initargs
- :view-size #@(30 100)
- :tick-mark-inc-fn #'(lambda (scale) (find-pixel-increment-v scale 1/4 1))) )
-
-
- (defclass number-line-horizontal-view (number-line-view)
- ()
- (:default-initargs
- :view-size #@(100 30)
- :tick-mark-inc-fn #'(lambda (scale) (find-pixel-increment-h scale 1/4 1))) )
-
-
- (defmethod initialize-instance ((view number-line-view) &rest initargs)
- (declare (ignore initargs))
- (call-next-method)
- (setf (number-line-rect view) (make-record :rect))
- (set-number-line-fonts view (title-font view) (mark-font view))
- (set-view-size view (view-size view)) )
-
-
- (defmethod remove-view-from-window ((view number-line-view))
- (dispose-record (number-line-rect view) :rect)
- (call-next-method))
-
-
- (defmethod set-number-line-fonts ((view number-line-view) title-font mark-font)
- (multiple-value-bind (ff ms) (font-codes title-font)
- (setf (title-ff view) ff)
- (setf (title-ms view) ms))
- (multiple-value-bind (ff ms) (font-codes mark-font)
- (setf (mark-ff view) ff)
- (setf (mark-ms view) ms)))
-
-
-
- ;;;;
- ;;;; RESIZING
- ;;;;
-
- (defmethod set-view-size ((view number-line-view) h &optional v)
- (declare (ignore h v))
- (invalidate-view view t)
- (call-next-method)
- (set-number-line-size view) )
-
-
- (defmethod set-number-line-scale ((view number-line-view))
- (let ((delta (- (end-value view) (start-value view))))
- (if (plusp delta)
- (setf (number-line-scale view) (/ (number-line-length view) delta))) ))
-
-
- ;;;
- ;;; Horizontal
- ;;;
-
- (defmethod number-line-length ((view number-line-horizontal-view))
- (point-h (view-size view)))
-
-
- (defmethod set-number-line-size ((view number-line-horizontal-view))
- (rset (number-line-rect view) rect.top 0)
- (rset (number-line-rect view) rect.left 0)
- (rset (number-line-rect view) rect.bottom
- (+ (number-line-width view) (line-height (mark-font view))))
- (rset (number-line-rect view) rect.right (point-h (view-size view)))
- (set-number-line-scale view))
-
-
- ;;;
- ;;; Vertical
- ;;;
-
- (defmethod number-line-length ((view number-line-vertical-view))
- (point-v (view-size view)))
-
-
- (defmethod set-number-line-size ((view number-line-vertical-view))
- (rset (number-line-rect view) rect.top 0)
- (rset (number-line-rect view) rect.left
- (- (point-h (view-size view))
- (number-line-width view)
- (max (string-width (princ-to-string (* 10 (end-value view))) (mark-font view))
- (string-width (princ-to-string (* 10 (start-value view))) (mark-font view)))))
- (rset (number-line-rect view) rect.bottomright (view-size view))
- (set-number-line-scale view))
-
-
-
- ;;;;
- ;;;; DRAWING
- ;;;;
-
- (defmethod view-draw-contents ((view number-line-view))
- (call-next-method)
- (with-focused-view view
- (with-fore-color (part-color view :title)
- (with-font-codes (title-ff view) (title-ms view)
- (draw-line-title view)))
- (draw-number-line view) ))
-
-
- (defmethod draw-number-line ((view number-line-view))
- (let ((left (rref (number-line-rect view) rect.left))
- (top (rref (number-line-rect view) rect.top))
- (right (rref (number-line-rect view) rect.right))
- (bottom (rref (number-line-rect view) rect.bottom)))
-
- (with-GWorld-no-colorization (view left top right bottom)
- (with-fore-color (part-color view :frame)
- (draw-number-bar view)
- (draw-number-line-tick-marks view))
- (with-fore-color (part-color view :numbers)
- (with-font-codes (mark-ff view) (mark-ms view)
- (draw-number-line-numbers view))) )))
-
-
- ;;;
- ;;; Horizontal
- ;;;
-
- (defmethod draw-line-title ((view number-line-horizontal-view))
- (do* ((i 0 (1+ i))
- (center (round (point-h (view-size view)) 2))
- (title (title view))
- (separation (line-height (title-font view)))
- (start-v (round (+ (number-line-width view)
- (* 2 (line-height (mark-font view))))))
- (rest-text title (rest rest-text))
- (text (first rest-text) (first rest-text))
- (width (if text (string-width text)) (if text (string-width text))) )
- ((null text))
- (#_MoveTo :long (make-point (- center (round width 2)) (+ start-v (* i separation))))
- (with-pstrs ((di-title text))
- (#_DrawString :ptr di-title)) ))
-
-
- (defmethod draw-number-bar ((view number-line-horizontal-view))
- (let* ((bottom (number-line-width view))
- (right (- (point-h (view-size view)) 2))
- (middle (round bottom 2))
- (old-pn (pref (wptr *GW-offscreen-view*) windowRecord.pnsize)))
- (with-port (wptr *GW-offscreen-view*) (#_PenSize :long #@(2 2)))
- (#_MoveTo :long (make-GW-point #@(0 0)))
- (#_LineTo :long (make-GW-point 0 bottom))
- (#_MoveTo :long (make-GW-point right 0))
- (#_LineTo :long (make-GW-point right bottom))
- (#_MoveTo :long (make-GW-point 0 middle))
- (#_LineTo :long (make-GW-point right middle))
- (with-port (wptr *GW-offscreen-view*) (#_PenSize :long old-pn))) )
-
-
- (defmethod draw-number-line-tick-marks ((view number-line-horizontal-view))
- (do* ((increment (funcall (tick-mark-inc-fn view) (number-line-scale view)))
- (current-mark (* (ceiling (start-value view) increment) increment)
- (+ current-mark increment))
- (start 0)
- (end (number-line-width view))
- (end-value (end-value view))
- (mark-position (line-number-position view current-mark)
- (line-number-position view current-mark)))
- ((> current-mark end-value))
- (#_MoveTo :long (make-GW-point mark-position start))
- (#_LineTo :long (make-GW-point mark-position end)) ))
-
-
- (defmethod draw-number-line-numbers ((view number-line-horizontal-view))
- (do* ((string-fn (string-trans-fn view))
- (end (+ (number-line-width view) (line-height (mark-font view))))
- (size (point-h (view-size view)))
- (increment (funcall (tick-mark-inc-fn view) (number-line-scale view)))
- (current-mark (* (ceiling (start-value view) increment) increment)
- (+ current-mark increment))
- (mark-string (funcall string-fn current-mark)
- (funcall string-fn current-mark))
- (width (string-width mark-string)
- (string-width mark-string))
- (mark-position (line-number-position view current-mark)
- (line-number-position view current-mark)))
- ((> current-mark (end-value view)))
-
- (#_MoveTo :long (make-GW-point (value-in-range 0 (- mark-position (round width 2)) (- size width))
- end))
- (with-pstrs ((di-title mark-string))
- (#_DrawString :ptr di-title)) ))
-
-
- ;;;
- ;;; Vertical
- ;;;
-
- (defmethod draw-line-title ((view number-line-vertical-view))
- (do* ((i 0 (1+ i))
- (center (round (- (point-h (view-size view)) (* 1.9 (number-line-width view))) 2))
- (title (title view))
- (separation (- (line-height (title-font view)) 2))
- (start-v (max separation
- (- (round (point-v (view-size view)) 2)
- (round (* (length title) separation) 2))))
- (rest-text title (rest rest-text))
- (text (first rest-text) (first rest-text))
- (width (if text (string-width text)) (if text (string-width text))) )
- ((null text))
- (#_MoveTo :long (make-point (- center (round width 2))
- (+ start-v (* i separation))))
- (with-pstrs ((di-title text))
- (#_DrawString :ptr di-title)) ))
-
-
- (defmethod draw-number-bar ((view number-line-vertical-view))
- (let* ((bottom (- (point-v (view-size view)) 2))
- (left (- (point-h (view-size view)) (number-line-width view)))
- (right (+ left (number-line-width view)))
- (middle (+ (round (number-line-width view) 2) left))
- (old-pn (pref (wptr *GW-offscreen-view*) windowRecord.pnsize)))
- (with-port (wptr *GW-offscreen-view*) (#_PenSize :long #@(2 2)))
- (#_MoveTo :long (make-GW-point left 0))
- (#_LineTo :long (make-GW-point right 0))
- (#_MoveTo :long (make-GW-point left bottom))
- (#_LineTo :long (make-GW-point right bottom))
- (#_MoveTo :long (make-GW-point middle 0))
- (#_LineTo :long (make-GW-point middle bottom))
- (with-port (wptr *GW-offscreen-view*) (#_PenSize :long old-pn)) ))
-
-
- (defmethod draw-number-line-tick-marks ((view number-line-vertical-view))
- (do* ((increment (funcall (tick-mark-inc-fn view) (number-line-scale view)))
- (current-mark (* (ceiling (start-value view) increment) increment)
- (+ current-mark increment))
- (end-value (end-value view))
- (start (- (point-h (view-size view)) (number-line-width view)))
- (end (+ start (number-line-width view)))
- (mark-position (line-number-position view current-mark)
- (line-number-position view current-mark)))
- ((> current-mark end-value))
- (#_MoveTo :long (make-GW-point start mark-position))
- (#_LineTo :long (make-GW-point end mark-position)) ))
-
-
- (defmethod draw-number-line-numbers ((view number-line-vertical-view))
- (do* ((vertical-mark-correction (round (line-height (mark-font view)) 3))
- (increment (funcall (tick-mark-inc-fn view) (number-line-scale view)))
- (end-value (end-value view))
- (string-fn (string-trans-fn view))
- (start (- (point-h (view-size view)) (number-line-width view)))
- (min-y-pos (- (line-height (mark-font view)) 3))
- (max-y-pos (point-v (view-size view)))
- (current-mark (* (ceiling (start-value view) increment) increment)
- (+ current-mark increment))
- (mark-string (funcall string-fn current-mark)
- (funcall string-fn current-mark))
- (width (string-width mark-string)
- (string-width mark-string))
- (mark-position (line-number-position view current-mark)
- (line-number-position view current-mark)))
- ((> current-mark end-value))
-
- (#_MoveTo :long (make-GW-point (- start width)
- (value-in-range min-y-pos (+ mark-position vertical-mark-correction) max-y-pos)))
- (with-pstrs ((di-title mark-string))
- (#_DrawString :ptr di-title)) ))
-
-
-
- ;;;;
- ;;;; USER MANIPULATION
- ;;;;
-
- (defmethod view-click-event-handler ((view number-line-view) where)
- (declare (ignore where))
-
- (when (point-in-rect-p (number-line-rect view) (view-mouse-position view))
- (let ((end (end-value view))
- (scale (number-line-scale view)))
- (cond ((and (rescale-p view) (shift-key-p)) (user-drag-end-value view))
- ((scroll-p view) (user-scroll-range view)))
- (when (or (= scale (number-line-scale view)) (/= end (end-value view)))
- (dialog-item-action view)) )))
-
-
- (defmethod user-drag-end-value ((view number-line-view))
- (declare (inline draw-number-line set-number-line-scale line-position-length))
- (do* ((length (number-line-length view))
- (start (start-value view))
- (min (min-value view))
- (max (max-value view))
- (old-click-value (line-position-length view (view-mouse-position view)))
- (mouse-position (max (line-point-value view (view-mouse-position view)) 1)
- (max (line-point-value view (view-mouse-position view)) 1))
- (old-end-value (end-value view) end-value)
- (end-value (value-in-range min (+ (round (* length old-click-value) mouse-position) start) max)
- (value-in-range min (+ (round (* length old-click-value) mouse-position) start) max)))
- ((not (mouse-down-p)))
- (when (/= end-value old-end-value)
- (setf (end-value view) end-value)
- (set-number-line-scale view)
- (draw-number-line view))))
-
-
- (defmethod user-scroll-range ((view number-line-view))
- (declare (inline draw-number-line set-number-line-scale line-position-length))
- (do* ((old-click-value (line-position-length view (view-mouse-position view)))
- (original-start (start-value view))
- (original-end (end-value view))
- (range (- original-end original-start))
- (min (min-value view))
- (max (max-value view))
- (mouse-position (view-mouse-position view)
- (view-mouse-position view))
- (new-value (line-position-length view mouse-position)
- (line-position-length view mouse-position))
- (delta (- old-click-value new-value)
- (- old-click-value new-value))
- (old-start-value (start-value view) start-value)
- (start-value (value-in-range min (+ original-start delta) (- max range))
- (value-in-range min (+ original-start delta) (- max range))))
- ((not (mouse-down-p)))
- (when (/= start-value old-start-value)
- (setf (start-value view) start-value)
- (setf (end-value view) (+ start-value range))
- (draw-number-line view))))
-
-
- ;;;;
- ;;;; UNIT TRANSLATION
- ;;;;
-
- ;;;
- ;;; Horizontal
- ;;;
-
- (defmethod line-number-position ((view number-line-horizontal-view) number)
- (round (* (- number (start-value view)) (number-line-scale view))))
-
-
- (defmethod line-position-length ((view number-line-horizontal-view) point)
- (round (point-h point) (number-line-scale view)))
-
-
- (defmethod line-position-number ((view number-line-horizontal-view) position)
- (declare (inline line-position-length))
- (+ (start-value view) (line-position-length view position)))
-
-
- (defmethod line-point-value ((view number-line-horizontal-view) point)
- (point-h point))
-
-
-
- ;;;
- ;;; Vertical
- ;;;
-
- (defmethod line-number-position ((view number-line-vertical-view) number)
- (round (- (point-v (view-size view))
- (* (- number (start-value view)) (number-line-scale view)))) )
-
-
- (defmethod line-position-length ((view number-line-vertical-view) point)
- (round (- (point-v (view-size view)) (point-v point)) (number-line-scale view)))
-
-
- (defmethod line-position-number ((view number-line-vertical-view) position)
- (declare (inline line-position-length))
- (+ (start-value view) (line-position-length view position)))
-
-
- (defmethod line-point-value ((view number-line-vertical-view) point)
- (declare (inline number-line-length))
- (- (number-line-length view) (point-v point)))
-
-
-
- ;;;;
- ;;;; CURSOR
- ;;;;
-
- (defmethod view-cursor ((view number-line-view) point)
- (if (point-in-rect-p (number-line-rect view) point)
- (cond ((and (shift-key-p) (rescale-p view)) (rescale-cursor view))
- ((scroll-p view) (scroll-cursor view))
- (t *arrow-cursor*))
- (call-next-method)))
-
-
-
- ;;;;
- ;;;; USER FUNCTIONS
- ;;;;
-
- (defmethod number-line-start ((view number-line-view))
- (start-value view))
-
-
- (defmethod number-line-end ((view number-line-view))
- (end-value view))
-
-
- (defmethod set-number-line-range ((view number-line-view) start end)
- (setf (start-value view) start)
- (setf (end-value view) end)
- (set-number-line-scale view))
-
-
-
- (provide :number-line-view)
-
-
-